/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/
const PENDING = 'pending'
  const FULFILLED = 'fulfilled'
  const REJECTED = 'rejected'
  class myPromise {
    constructor (executor) {
      // 执行构造器异常处理
      try {
        executor (this.resolve, this.reject)
      } catch (e) {
        this.reject(e)
      }
    }
    status = PENDING;
    response = undefined;
    err = undefined
    successCallback = []
    failCallback = []
    resolve = (response) => {
      // 如果程序不是PENDING，组织程序向下执行
      if (this.status !== PENDING) return
      // 状态更改为成功
      this.status = FULFILLED
      // 保存成功后的值
      this.response = response
      while (this.successCallback.length) {
        this.successCallback.shift()()
      }
      
    } 
    reject = (err) => {
      // 如果程序不是PENDING，组织程序向下执行  
      if (this.status !== PENDING) return
      // 状态更改为失败
      this.status = REJECTED
      // 保存失败值
      this.err = response
      while (this.failCallback.length) {
        this.failCallback.shift()()
      }
    }
    then (successCallback, failCallback) {
      // then不传递函数处理
      successCallback = successCallback ? successCallback : response => response
      failCallback = failCallback ? failCallback : err => { throw err }
      let promiseTwo = new Promise((resolve, reject) => {
        if (this.status === FULFILLED) {
            // setTimeout 是为了异步获取到promiseTwo
            setTimeout(() => {
              try {
                let x = successCallback(this.response)
                // 判断x的值是普通值还是promise对象
                // 如果是普通值直接调用resolve
                // 如果是promise对象，查看promise对象返回的结果
                // 再根据promise对象返回的结果，决定调用resolve还是reject
                resolvePromise(promiseTwo, x, resolve, reject)
              } catch (e) {
                reject(e)
              }
            }, 0)
        } else if (this.status === REJECTED) {
            // setTimeout 是为了异步获取到promiseTwo
            setTimeout(() => {
              try {
                let x = failCallback(this.err)
                // 判断x的值是普通值还是promise对象
                // 如果是普通值直接调用resolve
                // 如果是promise对象，查看promise对象返回的结果
                // 再根据promise对象返回的结果，决定调用resolve还是reject
                resolvePromise(promiseTwo, x, resolve, reject)
              } catch (e) {
                reject(e)
              }
            }, 0)
        } else {
          // 等待  将成功回调、失败回调存储起来
          this.successCallback.push(() => {
            setTimeout(() => {
              try {
                let x = successCallback(this.response)
                // 判断x的值是普通值还是promise对象
                // 如果是普通值直接调用resolve
                // 如果是promise对象，查看promise对象返回的结果
                // 再根据promise对象返回的结果，决定调用resolve还是reject
                resolvePromise(promiseTwo, x, resolve, reject)
              } catch (e) {
                reject(e)
              }
            }, 0)
          })
          this.failCallback.push(() => {
            setTimeout(() => {
              try {
                let x = failCallback(this.err)
                // 判断x的值是普通值还是promise对象
                // 如果是普通值直接调用resolve
                // 如果是promise对象，查看promise对象返回的结果
                // 再根据promise对象返回的结果，决定调用resolve还是reject
                resolvePromise(promiseTwo, x, resolve, reject)
              } catch (e) {
                reject(e)
              }
            }, 0)
          })
        }
      })
      return promiseTwo
    }

    finally (callback) {
      return this.then(response => {
        return myPromise.resolve(callback()).then(() => response)
        // callback()
        // return response
      }, err => {
        return myPromise.resolve(callback()).then(() => { throw err })
        // callback()
        // throw err
      })
    }

    static all(array) {
      let result = []
      let index = 0
      return new myPromise((resolve, reject) => {
        function addData (key, value) {
          index++
          result[key] = value
          if (index === array.length) {
            resolve(result)
          }
        }
        for (let i = 0; i < array.length; i++) {
          let current = array[i]
          if (current instanceof myPromise) {
            // promise对象
            current.then(response => addData(i, response), err => reject(err))
          } else {
            // 普通值
            addData(i, array[i])
          }
        }
      })
    }

    static resolve (value) {
      if (value instanceof myPromise) return value
      return new Promise(resolve => resolve(value))
    }
  }

  function resolvePromise(x, resolve, reject) {
    // 识别promise对象自返回
    if (x === promiseTwo) {
      return reject(new TypeError(''))
    }
    if (x instanceof myPromise) {
      // promise对象
      x.then(respone => resolve(response), err => reject(err))
      x.then(resolve,reject)

    } else {
      resolve(x)
    }
  } 
  module.export = myPromise